package gin_http

import (
	"fmt"
	"gitee.com/captials-team/ubdframe/src/common/consts"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"gitee.com/captials-team/ubdframe/src/domain/converts"
	"gitee.com/captials-team/ubdframe/src/domain/dto"
	"gitee.com/captials-team/ubdframe/src/domain/dto/respdata"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"golang.org/x/time/rate"
	"net/http"
	"runtime/debug"
)

var EmptyHandlerFunc = func(ctx *gin.Context) {}

type ToAuthDataPacketFunc func(ctx *gin.Context) (*dto.AuthDataPacket, error)

// AuthHandler 授权处理handler
func AuthHandler(jwtAuth interfaces.ItfJwtParser) gin.HandlerFunc {
	return AuthByDataPacketFuncHandler(ParseAuthByJwtFunc(jwtAuth))
}

// ParseAuthByJwtFunc jwt解析auth的function
func ParseAuthByJwtFunc(jwtAuth interfaces.ItfJwtParser) ToAuthDataPacketFunc {
	return func(ctx *gin.Context) (*dto.AuthDataPacket, error) {
		token := ctx.GetHeader(consts.AcceptAuthorizationKey)
		if token == "" {
			return nil, fmt.Errorf("token empty")
		}

		return converts.TokenToAuthDataPacket(token, jwtAuth)
	}
}

// AuthByDataPacketFuncHandler 指定DataPacket解析func的auth handler
func AuthByDataPacketFuncHandler(f ToAuthDataPacketFunc) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		auth, err := f(ctx)
		if err != nil {
			ctx.AbortWithStatusJSON(http.StatusOK, respdata.CAuthDenied.MMsg(respdata.CAuthDenied.Msg+","+err.Error()))
			return
		}

		SetAuth(ctx, auth)

		ctx.Next()
	}
}

// PingHandler ping处理handler
func PingHandler(ctx *gin.Context) {
	ctx.String(http.StatusOK, "pong")
}

// HealthHandler 健康检查处理方法
func HealthHandler(ctx *gin.Context) {
	ctx.String(http.StatusOK, "ok")
}

// PanicHandler panic处理
func PanicHandler(ctx *gin.Context) {
	if err := recover(); err != nil {
		debug.PrintStack()
		fmt.Printf("panic:%s\n", err)
		ctx.JSON(http.StatusInternalServerError, respdata.CSysBusy)
		ctx.Abort()
		return
	}
	ctx.Next()
}

// MatchMethodHandler 请求方法匹配
func MatchMethodHandler(methods ...string) gin.HandlerFunc {
	m := map[string]bool{}
	for _, v := range methods {
		m[v] = true
	}
	return func(ctx *gin.Context) {
		if _, exist := m[ctx.Request.Method]; !exist {
			ctx.AbortWithStatus(http.StatusNotFound)
			return
		}
		ctx.Next()
	}
}

// QPSLimiterHandler qps限流处理,  r:1秒内平均速率，b:1秒内最大允许突发流量
func QPSLimiterHandler(r rate.Limit, b int) gin.HandlerFunc {
	limiter := rate.NewLimiter(r, b)
	return func(ctx *gin.Context) {
		if !limiter.Allow() {
			//ctx.AbortWithStatus(http.StatusNoContent)
			//ctx.AbortWithStatusJSON(http.StatusNoContent, respdata.CAccessTooMuch)

			ctx.JSON(http.StatusOK, respdata.CAccessTooMuch)
			ctx.Abort()
			return
		}

		ctx.Next()
	}
}

// OptionRequestHandler OPTION请求过滤
func OptionRequestHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		if ctx.Request.Method == http.MethodOptions {
			ctx.AbortWithStatus(http.StatusNoContent)
			return
		}
		ctx.Next()
	}
}

// CorsHandler 跨域handler
func CorsHandler(corsConfig ...cors.Config) gin.HandlerFunc {
	if len(corsConfig) == 0 {
		corsConfig = []cors.Config{cors.DefaultConfig()}
	}

	return cors.New(corsConfig[0])
}

// AddRequestIdHandler 添加requestId
var AddRequestIdHandler = func(requestIdField string) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		//改为直接ctx接收requestId
		ctx.Set("request_id", utils.NewRequestId())
	}
}
